package org.elanfox.cloud.mybatis.type;

import cn.hutool.core.util.BooleanUtil;
import lombok.SneakyThrows;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;
import org.elanfox.cloud.common.enums.base.CodeDescCommonEnum;
import org.elanfox.cloud.common.enums.base.CodeDescEnumHelper;
import org.elanfox.cloud.mybatis.base.Association;
import org.elanfox.cloud.mybatis.mapperhelper.SqlHelper;

import javax.persistence.Column;
import java.lang.reflect.Field;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * @author allan
 * @version 1.0.0
 * @date 2020/7/2
 */
@MappedTypes(Association.class)
public class AssociationTypeHandler extends BaseTypeHandler<Association> {
    private final Class<Association> type;

    public AssociationTypeHandler(Class<Association> type) {
        if (type == null) {
            throw new IllegalArgumentException("Type argument cannot be null");
        }
        this.type = type;
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Association parameter, JdbcType jdbcType) throws SQLException {
        ps.setObject(i, parameter.getId());
    }

    @SneakyThrows
    @Override
    public Association getNullableResult(ResultSet rs, String columnName) throws SQLException {
        Object object = rs.getObject(columnName);
        if (object == null) {
            return null;
        }
        //组装
        Association association = type.newInstance();
        String tableAlias = SqlHelper.getTableAlias(type);
        tableAlias = "_" + columnName;
        Field[] fields = type.getDeclaredFields();
        for (Field field : fields) {
            Column column = field.getAnnotation(Column.class);
            Object val = rs.getObject(tableAlias + "." + column.name());

            if (CodeDescCommonEnum.class.isAssignableFrom(field.getType())) {
                val = CodeDescEnumHelper.getEnumTypeByCode(field.getType(), val);
            }
            field.setAccessible(true);
            if (BooleanUtil.isBoolean(field.getType())) {
                Integer v = (Integer) val;
                field.set(association, v == 1);
            } else {
                field.set(association, val);
            }
        }

        return association;
    }

    @Override
    public Association getNullableResult(ResultSet rs, int columnIndex) throws SQLException {

        return null;
    }

    @Override
    public Association getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return null;
    }
}
